import { WsClient, WsConnection, WsServer } from "tsrpc";
import { v4 } from "uuid";
import { getGameConfig } from "./gameConfigMgr";
import { getGameClusterClient } from "./getGateClusterClient";
import { serviceProto as GameServiceProto, ServiceType as GameServiceType } from "./shared/gameClient/protocols/serviceProto";
import { logger } from "./shared/tsgf/logger";
import { GameConnMgr } from "./GameConnMgr";
import { ServiceType as GameClusterServiceType } from "./shared/gameCluster/protocols/serviceProto";

/**游戏服务端的客户端连接*/
export type ClientConnection = WsConnection<GameServiceType>;
export type GameServer = WsServer<GameServiceType>;
type GameClusterClient = WsClient<GameClusterServiceType>;

/**拓展字段*/
declare module 'tsrpc' {
    export interface BaseConnection {
        /**连接ID,连接在服务端唯一标识*/
        connectionId: string;
    }
}

var serverCfg = getGameConfig();

//==========================================================
// 游戏服务
//==========================================================
/**全局唯一的游戏服务对象*/
export const gameServer: GameServer = new WsServer(GameServiceProto, {
    port: serverCfg.gameServer.listenPort,
    json: false,
    logger: logger,
});
//设置游戏服务连接ID
gameServer.flows.postConnectFlow.push(async v => {
    v.connectionId = v4();
    return v;
});
//初始化游戏连接管理器
export const gameConnMgr = new GameConnMgr(gameServer);




//==========================================================
// 游戏服务器集群
//==========================================================

/**全局唯一的游戏服务器集群客户端*/
let gameClusterClient!: GameClusterClient;
let gameClusterCAutoReconnectHD: any;

/**
 * 连接游戏集群服务器,失败返回错误消息
 * @returns cluster join 
 */
export async function joinGameCluster(): Promise<string | null> {
    if(gameClusterClient && gameClusterClient.isConnected)gameClusterClient.disconnect();
    gameClusterClient = getGameClusterClient();
    var connectRet = await gameClusterClient.connect();
    if (!connectRet.isSucc) {
        return "连接失败:" + connectRet.errMsg;
    }
    var serverCfg = getGameConfig();
    let ret = await gameClusterClient.callApi("JoinCluster", {
        serverInfo: {
            serverId: serverCfg.gameServer.serverId,
            serverName: serverCfg.gameServer.serverName,
            serverWSUrl: serverCfg.gameServer.serverWSUrl,
            clientCount: gameServer.connections.length,
            extendData: serverCfg.gameServer.extendData,
        },
        clusterKey: serverCfg.gameServer.clusterKey,
    });
    if (!ret.isSucc) {
        return ret.err.message;
    }
    //成功连上后,设置集群断开自动重连
    gameClusterClient.flows.postDisconnectFlow.push(async v => {
        if (!v.isManual) {
            gameServer.logger?.error('集群服务器-连接断开,等待2秒后自动重连');
            clearTimeout(gameClusterCAutoReconnectHD);
            gameClusterCAutoReconnectHD = setTimeout(reJoinGameCluster, 2000);
        }
        return v;
    });
    return null;
}
/**
 * 当集群断开后用于重新连接集群
 * @param [failReTry] 
 * @returns join game cluster 
 */
async function reJoinGameCluster(failReTry: boolean = true): Promise<boolean> {
    const err = await joinGameCluster();
    // 重连也错误，弹出错误提示
    if (!err) {
        gameServer.logger?.log('集群服务器-重连成功!');
        return true;
    }
    if (failReTry) {
        gameServer.logger?.error('集群服务器-重连失败:' + err + '  2秒后自动重连!');
        clearTimeout(gameClusterCAutoReconnectHD);
        setTimeout(() => reJoinGameCluster(failReTry), 2000);
    } else {
        gameServer.logger?.error('集群服务器-重连失败:' + err);
    }
    return false;
}

